package system

import (
	"context"
	model "gf-vben-admin/internal/model/system"
	"gf-vben-admin/internal/model/system/entity"
	"gf-vben-admin/internal/service/system/internal/dao"
	"gf-vben-admin/internal/service/system/internal/do"
	utils "gf-vben-admin/utility"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
)

type (
	sRole struct{}
)

var (
	insRole = sRole{}
)

func Role() *sRole {
	return &insRole
}

func (s *sRole) PageList(ctx context.Context, param model.Role) (total int, result []*entity.Role, err error) {
	result = make([]*entity.Role, 0)
	daoModel := dao.Role.Ctx(ctx)
	columnMap := dao.Role.ColumnMap()
	daoModel, err = utils.GetWrapper(param, daoModel, columnMap)
	if err != nil {
		return
	}
	total, err = daoModel.Count()
	if err != nil {
		g.Log().Error(ctx, err)
		err = gerror.New("获取总行数失败")
		return
	}
	if total == 0 {
		return
	}
	err = daoModel.Page(param.PageNum, param.PageSize).Scan(&result)
	if err != nil {
		g.Log().Error(ctx, err)
		err = gerror.New("获取数据失败")
	}
	return
}

func (s *sRole) List(ctx context.Context, param entity.Role) (result []*entity.Role, err error) {
	result = make([]*entity.Role, 0)
	daoModel := dao.Role.Ctx(ctx)
	columnMap := dao.Role.ColumnMap()
	daoModel, err = utils.GetWrapper(param, daoModel, columnMap)
	if err != nil {
		return
	}
	err = daoModel.Scan(&result)
	if err != nil {
		g.Log().Error(ctx, err)
		err = gerror.New("获取数据失败")
	}
	return
}

// Get 查询角色表详情
func (s *sRole) Get(ctx context.Context, id int64) (result *entity.Role, err error) {
	result = new(entity.Role)
	daoModel := dao.Role.Ctx(ctx)
	err = daoModel.Where(dao.Role.Columns().Id, id).Scan(&result)
	if err != nil {
		g.Log().Error(ctx, err)
		err = gerror.New("获取数据失败")
	}
	return
}

func (s *sRole) Add(ctx context.Context, in model.Role) (err error) {
	err = dao.Role.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
		_, err := tx.Model(dao.Role.Table()).Ctx(ctx).OmitEmpty().Data(in).Insert()
		return err
	})
	return
}

func (s *sRole) Edit(ctx context.Context, in model.Role) (err error) {
	err = dao.Role.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
		_, err := tx.Model(dao.Role.Table()).Ctx(ctx).OmitEmpty().Data(in).Where(do.Role{
			Id:            in.Id,
			VersionNumber: in.VersionNumber,
		}).Update()
		return err
	})
	return
}

func (s *sRole) EditState(ctx context.Context, ids []int64, state int8) (err error) {
	err = dao.Role.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
		_, err := tx.Model(dao.Role.Table()).Ctx(ctx).Data(do.Role{State: state}).Where(do.Role{Id: ids}).Update()
		return err
	})
	return
}

func (s *sRole) Delete(ctx context.Context, ids []int64) (err error) {
	err = dao.Role.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
		_, err := tx.Model(dao.Role.Table()).Ctx(ctx).Where(do.Role{Id: ids}).Delete()
		return err
	})
	return
}

func (s *sRole) RoleScope(ctx context.Context, roleScope model.RoleScope) (err error) {
	permissions := roleScope.Permissions
	err = dao.RolePermission.Ctx(ctx).Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
		_, err = tx.Model(dao.RolePermission.Table()).Ctx(ctx).Where(do.RolePermission{RoleCode: roleScope.Id}).Delete()
		if err != nil {
			return err
		}
		rolePermissions := make([]entity.RolePermission, 0)
		for _, permission := range permissions {
			rolePermissions = append(rolePermissions, entity.RolePermission{
				TenantCode:     roleScope.TenantCode,
				RoleCode:       roleScope.Code,
				PermissionCode: permission.Code,
			})
		}
		_, err = tx.Model(dao.RolePermission.Table()).Ctx(ctx).Data(rolePermissions).OmitEmpty().Save()
		return err
	})
	return
}
